package main

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	if len(os.Args) < 3 {
		log.Fatalln("必须跟上ip 和 端口")
	}
	addr := os.Args[1]
	port := os.Args[2]

	ipAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%v:%v", addr, port))
	if err != nil {
		log.Fatal(err)
	}

	conn, err := net.DialTCP("tcp", nil, ipAddr)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	log.Println("已建立连接....")
	go func() {
		defer func() {
			if v := recover(); v != nil {
				log.Println(v)
			}
		}()

		result := bytes.NewBuffer(nil)
		var buf [65542]byte
		for {
			n, err := conn.Read(buf[0:])
			result.Write(buf[0:n])
			if err != nil {
				if err == io.EOF {
					continue
				} else {
					log.Println("handleCon for", err)
				}
			} else {
				scanner := bufio.NewScanner(result)
				scanner.Split(packetSlitFunc)
				for scanner.Scan() {
					r := scanner.Bytes()[6:]
					log.Println(string(r))
				}
			}
			result.Reset()
		}

	}()
	for {
		var str string
		fmt.Print("请输入：")
		if _, err := fmt.Scanln(&str); err != nil {
			log.Println(err.Error())
		}

		if _, err := conn.Write(sendPkg(str)); err != nil {
			log.Println("发送失败、服务断开： ", err.Error())
			return
		}
	}

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	<-sigs
	os.Exit(0)
}

func packetSlitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if !atEOF && len(data) > 6 && binary.BigEndian.Uint32(data[:4]) == 0x123456 {
		var l int16
		binary.Read(bytes.NewReader(data[4:6]), binary.BigEndian, &l)
		pl := int(l) + 6
		if pl <= len(data) {
			return pl, data[:pl], nil
		}
	}
	return
}

func sendPkg(msg string) []byte {
	bbys := []byte(msg)
	magicNum := make([]byte, 4)
	binary.BigEndian.PutUint32(magicNum, 0x123456)
	lenNum := make([]byte, 2)
	binary.BigEndian.PutUint16(lenNum, uint16(len(bbys)))
	packetBuf := bytes.NewBuffer(magicNum)
	packetBuf.Write(lenNum)
	packetBuf.Write(bbys)
	return packetBuf.Bytes()
}
